package svg;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.net.URI;
import java.util.ArrayList;

public class TaskCanvas extends GObject 
{
	/*
	 * Fonts for title and scaling information
	 */
	protected Font titleFont = null;
	protected Font scaleFont = null;
	
	/*
	 * Title width
	 */
	protected int titleWidth;
	
	/*
	 * Size of a gap between two components
	 */
	protected int gap = 5;
	
	/*
	 * Task period, deadline, total amount of time and scaling
	 */
	protected int period;
	protected int deadline;
	protected int timeSegment;
	protected int scale;
	
	/*
	 * Task name, graphics controller and a list of jobs
	 */
	protected String name = null;
	
	protected Graphics graphics = null;
	
	protected ArrayList<GObject> jobs;
	
	/*
	 * Number of pixels which represent 1 time unit
	 */
	protected double timeUnit;
	/*
	 * time axis starting point
	 */
	protected Point axisStarts;
	/*
	 * time axis ending point
	 */
	protected Point axisEnds;
	
	protected int axisArrowLength;
	
	public TaskCanvas(String name, Graphics graphics, 
			int timeSegment, int period, int deadline, int scale)
	{
		this(0, 0, 0, 0, name, graphics, timeSegment, period, deadline, scale);
	}
	/* TaskCanvas
	 * x - left top corner coordinate x
	 * y - left top corner coordinate y
	 * width - container width
	 * height - container height 
	 * name - a name of the task
	 * graphics - graphics controller
	 * timeSegment - total number of time units
	 * period - task period
	 * deadline - task deadline
	 * scale - number which will be depicted on Time axis
	 */
	public TaskCanvas(int x, int y, int width, int height, String name, Graphics graphics, 
			int timeSegment, int period, int deadline, int scale)
	{
		super(x, y, width, height);

		this.jobs = new ArrayList<GObject>();
		
		this.name = name;
		
		this.graphics = graphics;
		
		this.titleFont = new Font("SansSerif", Font.PLAIN, 16);
		this.scaleFont = new Font("SansSerif", Font.PLAIN, 12);
		
		FontMetrics titleMetrics = graphics.getFontMetrics(titleFont);
		titleWidth = titleMetrics.stringWidth(name);
		
		this.timeSegment = timeSegment;
		this.period = period;
		this.deadline = deadline;
		this.scale = scale;
		
		init();
	}
	
	public void init()
	{
		int axisPositionY = y + height - (int)((1.0 * height) / 3.0);
		this.axisStarts = new Point(x + titleWidth + 2 * gap, axisPositionY);
		this.axisEnds = new Point(x + width - gap, axisPositionY);
		
		this.axisArrowLength = 8;
		int axisLength = (int)(axisEnds.getX() - axisStarts.getX()) - axisArrowLength;
		this.timeUnit = (axisLength * 1.0) / (timeSegment * 1.0);
	}
	
	public void show(URI uri)
	{
		{
			// frame
			JobViewer.addRectangle(uri, x, y + height, width, 1, true, Color.WHITE, true, Color.BLACK, 1);
			// title
			JobViewer.writeText(uri, name, x, y + height / 2 + titleFont.getSize() / 2, titleFont, Color.BLACK);
			// axis
			JobViewer.addArrowedLine(uri, axisStarts, axisEnds, 
					JobViewer.ARROW_RIGHT, axisArrowLength, true, Color.WHITE, true, Color.BLACK, 1);
		}
		// all jobs
		for(GObject element: jobs)
		{
			element.show(uri);
		}
		// periods/deadlines
		{
			int arrowLength = 6;
			for(int i = 0; i < timeSegment / period; i++)
			{
				// period
				Point periodStart = new Point(new Integer((int)axisStarts.getX() + (int)(i * period * timeUnit)), (int)axisStarts.getY());
				Point periodEnd = new Point(new Integer((int)axisStarts.getX() + (int)(i * period * timeUnit)), (int)axisStarts.getY() - (int)((2.0 * height) / 3.0));
				JobViewer.addArrowedLine(uri, periodStart, periodEnd, 
						JobViewer.ARROW_UP, arrowLength, true, Color.GREEN, true, Color.GREEN, 1);
				// deadline
				Point deadlineStart = new Point(new Integer((int)periodStart.getX() + (int)(deadline * timeUnit)), (int)axisStarts.getY());
				Point deadlineEnd = new Point(new Integer((int)periodStart.getX() + (int)(deadline * timeUnit)), (int)axisStarts.getY() + (int)((1.0 * height) / 3.0));
				if(deadlineStart.getX() < axisEnds.getX())
				{
					JobViewer.addArrowedLine(uri, deadlineStart, deadlineEnd, 
							JobViewer.ARROW_DOWN, arrowLength, true, Color.RED, true, Color.RED, 1);	
				}
			}
		}
		// scale
		{
			FontMetrics scaleMetrics = graphics.getFontMetrics(scaleFont);
			for(int i = 0; i < timeSegment / scale; i++)
			{
				String scaleInfo = String.valueOf(i * scale);
				int scaleWidthX = scaleMetrics.stringWidth(scaleInfo);
				int scaleHeight = scaleMetrics.getHeight();
				JobViewer.writeText(uri, scaleInfo, 
						new Integer((int)axisStarts.getX() + (int)(i * scale * timeUnit - (1.0 * scaleWidthX) / 2.0)), 
						(int)axisStarts.getY() + scaleHeight, scaleFont, Color.BLACK);
			}
		}
	}
	
	public int getPeriod() {
		return period;
	}
	public void setPeriod(int period) {
		this.period = period;
	}
	public int getDeadline() {
		return deadline;
	}
	public void setDeadline(int deadline) {
		this.deadline = deadline;
	}

	public ArrayList<GObject> getJobs() {
		return jobs;
	}

	public void setJobs(ArrayList<GObject> jobs) {
		this.jobs = jobs;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Font getTitleFont() {
		return titleFont;
	}

	public void setTitleFont(Font titleFont) {
		this.titleFont = titleFont;
	}

	public Font getScaleFont() {
		return scaleFont;
	}

	public void setScaleFont(Font scaleFont) {
		this.scaleFont = scaleFont;
	}

	public int getGap() {
		return gap;
	}

	public void setGap(int gap) {
		this.gap = gap;
	}

	public int getTimeSegment() {
		return timeSegment;
	}

	public void setTimeSegment(int timeSegment) {
		this.timeSegment = timeSegment;
	}

	public int getScale() {
		return scale;
	}

	public void setScale(int scale) {
		this.scale = scale;
	}

	public Graphics getGraphics() {
		return graphics;
	}

	public void setGraphics(Graphics graphics) {
		this.graphics = graphics;
	}

	public double getTimeUnit() {
		return timeUnit;
	}

	public void setTimeUnit(double timeUnit) {
		this.timeUnit = timeUnit;
	}

	public Point getAxisStarts() {
		return axisStarts;
	}

	public void setAxisStarts(Point axisStarts) {
		this.axisStarts = axisStarts;
	}

	public Point getAxisEnds() {
		return axisEnds;
	}

	public void setAxisEnds(Point axisEnds) {
		this.axisEnds = axisEnds;
	}

	public int getAxisArrowLength() {
		return axisArrowLength;
	}

	public void setAxisArrowLength(int axisArrowLength) {
		this.axisArrowLength = axisArrowLength;
	}
	public int getTitleWidth() {
		return titleWidth;
	}
	public void setTitleWidth(int titleWidth) {
		this.titleWidth = titleWidth;
	}
}
